import math, os, sys, poser, random

os.chdir( os.path.dirname(poser.AppLocation()) )
sys.path.append(os.path.join("Runtime","Python","Poseworks","Particles3","data"))

from prt3Constants import *
from prt3Xml import *

global CURRENT_ACTOR
CURRENT_ACTOR = None

IMG_PANEL = 14001
IMG_TOPBAR = 14002
IMG_TOPBAR_O = 14003
IMG_X = 14004
IMG_X_O = 14005
IMG_BTN_OK = 14010
IMG_BTN_OK_O = 14011
IMG_BTN_NEXT = 14012
IMG_BTN_NEXT_O = 14013
IMG_BTN_CREATE = 14014
IMG_BTN_CREATE_O = 14015
IMG_BTN_SIM = 14016
IMG_BTN_SIM_O = 14017
IMG_DIV = 14020
IMG_BTN_QUESTION = 14501
IMG_BTN_QUESTION_O = 14502

FONT_HEADER = PzrText(size=24, font=1, color=PzrColor(55,41,9))
FONT_BODY = PzrText(size=12, font=1, color=PzrColor(107,102,93))
FONT_PARAMETER = PzrText(size=16, font=1, color=PzrColor(107,102,93))
FONT_PARM_DARK = PzrText(size=16, font=1, color=PzrColor(55,41,9))
FONT_RADIO = PzrText(size=14, font=1, color=PzrColor(107,102,93))

IMG_BALL = 14101
IMG_BALL_O = 14111
IMG_TORUS = 14102
IMG_TORUS_O = 14112
IMG_PILL = 14103
IMG_PILL_O = 14113
IMG_SPRITE = 14104
IMG_SPRITE_O = 14114
IMG_CONE = 14105
IMG_CONE_O = 14115
IMG_CUSTOM = 14106
IMG_CUSTOM_O = 14116

IMG_LOAD = 14801
IMG_LOAD_O = 14802

IMG_VELOCITY = 14904
IMG_ORBIT = 14901
IMG_SPIN = 14905
IMG_GROW = 14906
IMG_TRANSFORM = 14907
IMG_SIMULATION = 14908
IMG_EMITTER = 14910
IMG_ATTRACTOR = 14911

IMG_TIP_ACCELERATION = 14902
IMG_TIP_VARIANCE = 14903
IMG_TIP_GRAVITY = 14909

STRING_EXP_SPAWNING = "Spawning"
STRING_EXP_EMITTER = "Emitters"
STRING_EXP_EMITTER_INFO = """Emitters are the source of all particles. They control the direction, angle, and
initial position of each particle.

Particles spawn at the current location of the emitter.
"""
STRING_EXP_FIGURES = "Particle Figures"
STRING_EXP_PARTICLE = "Particles"

STRING_STARTEND = "Start/End Frame"
STRING_STARTEND_TIP = """The Start Frame is the first frame of your animation that particles will be spawned. For example, if you set
the Start Frame to 10, no particles will appear until frame 10.

The End Frame is the last frame of your animation that particles can be spawned. If you set the
End Frame to 30, new particles will stop appearing after frame 30. (Any existing particles will continue
to age and move.)

Setting the End Frame to -1 will automatically use the last frame in the animation."""

STRING_PARTICLE_SHAPE = "Particle Shape"
STRING_PARTICLE_SHAPE_INFO = """The shape you choose here will be used by each one
of the particles in the figure. Keep in mind:

How many particles are in the scene. A dense geometry
can slow down your machine if you have a large number
of particles in the scene.

Whether or not you want to use procedurals. Rounded
shapes are very effective for procedural materials, while
hard-edged shapes are better suited for transparency and
texture maps.

How disjointed the effect should be. Tapered and oblong
shapes are useful for jumbled, frothy systems."""

STRING_PARTICLE_COUNT = "Number of Particles"
STRING_PARTICLE_COUNT_TIP = """When you choose how many particles are in your scene,
you should keep in mind:

If you need to have a steady steam of particles coming from
the emitter. For example, if you have 3 particles spawned
every frame and a particle's lifespan is 30 frames, you need
90 particles. If you only have one particle spawning every
frame and its lifespan is 30 frames, then you only need 30
particles. ("Rate of Emission" times "Particle Lifespan")

The more particles you have in the scene, the longer it will
take to simulate, the more memory will be used and the
more disk space it will take to save your scene.

You can't change the number of particles later, so be sure
to give yourself a margin of error for added flexibility."""

STRING_PARTICLE_COUNT_TIP = """When you choose how many particles are in your scene, you should keep in mind:

If you need to have a steady steam of particles coming from the emitter. For example, if you have three
particles spawned every frame and a particle's lifespan is 30 frames, you need 90 particles. If you only
have one particle spawning every frame and its lifespan is 30 frames, then you only need 30 particles.
("Rate of Emission" times "Particle Lifespan")

The more particles you have in the scene, the longer it will take to simulate, the more memory will be used
and the more disk space it will take to save your scene. You can't change the number of particles later, so
be sure to give yourself a margin of error for added flexibility."""

STRING_PARTICLE_NAME = "Figure Name"
STRING_PARTICLE_NAME_TIP = """This is the name of the figure that will be created. The emitter will also be created using this name."""

STRING_BALL = "Ball"
STRING_BALL_TIP = """The ball is especially useful when you're using the
Material Room to create procedural shaders. Adding some
displacement with 3D Texture nodes, or using Edge_Blend
with transparency lets you create a wide range of different
effects."""

STRING_TORUS = "Torus"
STRING_TORUS_TIP = """Like the ball, the torus is most useful when combined with
Material Room magic. Torii can effective as smoke rings,
tornados and many other effects."""

STRING_PILL = "Pill"
STRING_PILL_TIP = """The pill is very versatile, like the ball, but has the added
benefit of being an oblong shape. That means that particle
figures using the pill shape can easily appear very active
and chaotic."""

STRING_SPRITE = "Sprite"
STRING_SPRITE_TIP = """The sprite lets you stamp a 2D image across your scene
in 3D space. By putting a transparency map on a sprite,
you can get a great memory advantage with complicated-
looking effects."""

STRING_CONE = "Cone"
STRING_CONE_TIP = """The cone is useful for effects like confetti and ice crystals,
where the particles will suddenly catch light from different
angles."""

STRING_CUSTOM = "Custom"
STRING_CUSTOM_TIP = """File/path/geom.obj"""

STRING_TRANSFORM = "Particle Transform"
STRING_TRANSFORM_TIP = """Controls that change the initial state of each particle.

Initial Scale sets how large the particle is when it is spawned.

Initial Rotation controls the angle of the particle on each axis
when it is spawned.

Initial Offset controls the distance between the particle and the
emitter when it is spawned. Remember that particles come
from the emitter radially, so setting Initial Offset X to 1.0
will create a circle of particles around the emitter with a radius
of 1.0."""

STRING_SIMULATION = "Simulation"
STRING_SIMULATION_TIP = """These options affect how the particle figure behaves once
particles need to be spawned and start moving.

Rate of Emission is how many particles spawn per frame. Recycle
Particles allows dead particles to spawn again. Particle Lifespan
sets the number of frames that a particle will live after it's spawned."""

STRING_VELOCITY = "Velocity"
STRING_VELOCITY_TIP = """Velocity causes particles to move in a direction. For instance,
Velocity Y causes particles to move up along their spawn vectors.

Velocity is measured in Poser units per second, so a Velocity Y of
1.0 will move particles up 1.0 units per second. In Poser, there is
a default of 30 frames per second. """

STRING_ORBIT = "Orbit"
STRING_ORBIT_TIP = """Orbit causes the particles to move around an axis, like the
planets orbit around the sun.

If Orbit Y is 15, particles will Y-Rotate 15 degrees per frame
around wherever the emitter was when the particle spawned."""

STRING_SPIN = "Spin"
STRING_SPIN_TIP = """Spin causes each particle to rotate on its own axis.

If Spin Y is 15, particles will Y-Rotate 15 degrees per frame.

If Spin X is -15, particles will X-Rotate -15 degrees per frame."""

STRING_GROW = "Grow"
STRING_GROW_TIP = """The Grow properties cause particles to change in scale.

If Grow Y is 2, particles will increase in Y-Scale by 2% every
frame. If Grow Y is -2, particles will shrink vertically by 2%
every frame."""

STRING_RUN_SIMS = "Simulation Options"

STRING_SIMULATE_IN_PLACE = "Simulate in place for"
STRING_SIMULATE_IN_PLACE_INFO = """This option causes the simulation to run on the start frame X number of times, and then proceed. You can use
this option to make the particle figure more fully formed than it would be otherwise. Typically, if you use this
option, you should set it to be the same as the particle figure's Lifespan, so that the particle figure has gone
through one complete cycle."""

STRING_EMITTER = "Emitters"
STRING_EMITTER_TIP = """The position of an emitter controls the place where particles spawn. The rotation of the emitter controls the
direction that particles move in.

The Angle of Emission property changes how wide the spread of spawn vectors is. A low Angle of Emission
keeps the particles focused like a laser, while a wide angle makes the particles spread out like a
dandelion head."""

STRING_ATTRACTOR = "Attractors"
STRING_ATTRACTOR_TIP = """Attractors draw particles towards them or push particles away.

An attractor's Strength controls how much it pulls on particles.
A negative Strength value will push particles away.

An attractor's Range determines how far away particles can
be and still be affected by the attractor.

An attractor's Falloff controls how the attractor's Strength
changes as particles are closer or further from the center.
"""

STRING_RUN_SIMS_FOR = "Run simulation for:"

STRING_SELECTED_FIG = "Selected particle figure."

STRING_ALL_FIG = "All particle figures."

STRING_THESE_FIG = "These particle figures:"

class PwParticles3Shape(object):
        def __init__(self, default=None):
                self.shape_numbers = {GEOM_BALL: SHAPE_BALL,
                                      GEOM_TORUS: SHAPE_TORUS,
                                      GEOM_PILL: SHAPE_PILL,
                                      GEOM_SPRITE: SHAPE_SPRITE,
                                      GEOM_CONE: SHAPE_CONE}
                self.shape_strings = {GEOM_BALL: STRING_BALL,
                                      GEOM_TORUS: STRING_TORUS,
                                      GEOM_PILL: STRING_PILL,
                                      GEOM_SPRITE: STRING_SPRITE,
                                      GEOM_CONE: STRING_CONE}
                self.shape_geoms = {STRING_BALL: GEOM_BALL,
                                   STRING_TORUS: GEOM_TORUS,
                                   STRING_PILL: GEOM_PILL,
                                   STRING_SPRITE: GEOM_SPRITE,
                                   STRING_CONE: GEOM_CONE}
                if not default:
                        self.geom = PRT3_PREFS.Get("shape")
                else:
                        self.geom = default
        def Set(self, path):
                self.geom = path
        def Name(self):
                if self.shape_strings.has_key(self.geom):
                        return self.shape_strings[self.geom]
                else:
                        return "%s - %s" % (STRING_CUSTOM, os.path.basename(self.geom))
        def Shape(self):
                if self.shape_numbers.has_key(self.geom):
                        return self.shape_numbers[self.geom]
                else:
                        return SHAPE_CUSTOM
        def Geometry(self):
                return self.geom

class PwParticles3Div(PzrImage):
        def __init__(self, widgetName):
                PzrImage.__init__(self, widgetName, width=364, height=2, pictRes=IMG_DIV)

class PwParticles3Parameter(PzrGUIObject):
        def __init__(self, widgetName, command=10001, label=None, default=0, textwidth=176, suffix="", font=FONT_PARAMETER):
                self.widgetName = widgetName
                if label:
                        self.label = label
                else:
                        self.label = self.widgetName
                self.default = default
                self.textwidth = textwidth
                self.suffix = suffix
                if isinstance(default, int):
                        self.btn = PzrIntButton(self.widgetName, command=command, text=default, value=default, message=label, suffix=suffix)
                elif isinstance(default, float):
                        self.btn = PzrFloatButton(self.widgetName, command=command, text=default, value=default, message=label, suffix=suffix)
                elif isinstance(default, str):
                        if default == "True" or default == "False":
                                if default == "True":
                                        v = 1
                                else:
                                        v = 0
                                self.btn = PzrBoolButton(self.widgetName, command=command, text=default, value=v, message=label)
                        else:
                                self.textwidth = 108
                                self.btn = PzrStringButton(self.widgetName, command=command, text=default, value=default, message=label)
                else:
                        self.btn = PzrFloatButton(self.widgetName, command=command, text=default, value=default, message=label)
                self.msg = PzrMessage(self.widgetName + "Msg", command=command, text=font)
        def place(self, x, y):
                self.xml = "\n" + self.msg.place(x, y) +\
                       "\n" + self.btn.place(x + self.textwidth, y)
                return self.xml
        def SetText(self, dialog, message):
                self.msg.SetText(dialog, message)
        def SetDialog(self, dialog):
                self.dialog = dialog
                self.msg.SetDialog(dialog)
                self.btn.SetDialog(dialog)
                if self.label:
                        self.SetText(dialog, self.label)
                else:
                        self.SetText(dialog, self.widgetName)
        def SetValue(self, value):
                self.btn.Set(value)
        def Name(self):
                return self.label
        def Value(self):
                return self.btn.get()

class PwParticles3ParameterList(PzrGUIObject):
        def __init__(self, widgetName, header=None, command=10001, spacing=2, tip=None):
                self.widgetName = widgetName
                self.header = header
                self.tipBtn = None
                if self.header:
                        self.msg = PzrMessage(self.widgetName + "Header", text=FONT_HEADER, bb=PzrRect(left=0, top=0, right=290, bottom=42), command=command)
                        self.msg.configure(title=self.header)
                        if tip:
                                self.tipBtn = PzrImageButton(self.widgetName + "Tip", pictRes=IMG_BTN_QUESTION, hiliteRes=IMG_BTN_QUESTION_O, width=18, height=19, command=command, callback=tip)
                self.parameters = []
                self.curCommand = command + 1
                self.spacing = spacing
        def addParameter(self, label, default):
                wname = self.widgetName + repr(len(self.parameters))
                self.parameters.append( PwParticles3Parameter(wname, command=self.curCommand, label=label, default=default) )
                self.curCommand = self.curCommand + 1
        def place(self, x, y):
                self.xml = ""
                i = y
                if self.header:
                        self.xml = self.xml + "\n" + self.msg.place(x, i)
                        if self.tipBtn:
                                self.xml = self.xml + "\n" + self.tipBtn.place(x + 176, i+6)
                        i = i + 32
                if self.parameters:
                        self.xml = self.xml + "\n" + PwParticles3Div(self.widgetName + "Div").place(x - 16, i - 2)
                for parm in self.parameters:
                        self.xml = self.xml + "\n" + parm.place(x, i + 4) +\
                                   "\n" + PwParticles3Div(parm.widgetName + "Div %i" % i).place(x - 16, i + 28)
                        i = i + 32
                return self.xml
        def Height(self):
                return 32 + len(self.parameters) * 32
        def SetDialog(self, dialog):
                self.dialog = dialog
                if self.header:
                        self.msg.SetDialog(dialog)
                if self.tipBtn:
                        self.tipBtn.SetDialog(dialog)
                for parm in self.parameters:
                        parm.SetDialog(dialog)
        def Values(self):
                values = {}
                for parm in self.parameters:
                        values[parm.Name()] = parm.Value()
                return values

class PwParticles3Info(PzrGUIObject):
        def __init__(self, widgetName, header, body):
                self.widgetName = widgetName
                self.header = header
                self.body = body
                self.title = PzrMessage(self.widgetName + "Title", text=FONT_HEADER)
                self.title.configure(title=self.header)
                self.divider = PwParticles3Div(self.widgetName + "Div")
                self.info = PzrTextArea(self.widgetName + "Text", text=FONT_BODY, message=self.body)
                self.dialog = None
        def SetBody(self, info):
                self.body = info
                if self.dialog:
                        self.info.SetText(self.dialog, info)
        def SetHeader(self, header):
                self.header = header
                if self.dialog:
                        self.title.SetText(self.dialog, header)
        def SetDialog(self, dialog):
                self.dialog = dialog
                self.title.SetDialog(dialog)
                self.divider.SetDialog(dialog)
                self.info.SetDialog(dialog)
        def Update(self):
                self.SetBody(self.body)
                self.SetHeader(self.header)
        def place(self, x, y):
                return "\n" + self.title.place(x + 22, y) +\
                       "\n" + self.divider.place(x, y + 28) +\
                       "\n" + self.info.place(x + 22, y + 34)

class PwParticles3Dialog(PzrDialog):
        def __init__(self, width=640, height=480, xmlpath="tempDlg.xml",
                     infoHeader=None, infoBody=None,
                     tipHeader=None, tipBody=None,
                     confirmbtn=IMG_BTN_OK, confirmcmd=CMD_ACCEPT, confirmcb=None):
                PzrDialog.__init__(self, width=width, height=height, xmlpath=xmlpath, borders=0, palettes="./runtime/python/poseworks/particles3/resources/14000_panel.psd")
                self.add( PzrImage("bg", width=640, height=480, pictRes=IMG_PANEL), 0, 0)
                self.add( PzrImageButton("img", command=11000, width=640, height=54, pictRes=IMG_TOPBAR, hiliteRes=IMG_TOPBAR_O, behaviorProcID=BID_DRAG), 0, 6)
                self.add(PzrImageButton("accept", command=confirmcmd, callback=confirmcb, width=226, height=39, pictRes=confirmbtn, hiliteRes=confirmbtn + 1), 411, 439)
                self.add(PzrImageButton("reject", command=CMD_REJECT, width=49, height=31, pictRes=IMG_X, hiliteRes=IMG_X_O), 577, 13)
                self.info, self.tip = None, None
                if infoHeader and infoBody:
                        self.info = PwParticles3Info("infoBox", infoHeader, infoBody)
                        self.add(self.info, 7, 71)
                if tipHeader and tipBody:
                        self.tip = PwParticles3Info("tipBox", tipHeader, tipBody)
                        self.add(self.tip, 7, 322)
                self.parameterlists = []
                self.parmsy = 75
                self.curCommand = 10001
        def SetInfo(self, header, body):
                self.info.SetHeader(header)
                self.info.SetBody(body)
        def SetTip(self, header, body):
                self.tip.SetHeader(header)
                self.tip.SetBody(body)
        def AddIllustration(self, img, width=310, height=218, x=0, y=0):
                if not x:
                        x = (320-width)/2 + 20
                if not y:
                        y = (240-height)/2 + 71
                self.add(PzrImage("illustration", pictRes=img, width=width, height=height), x, y)
        def AddParameterList(self, header, parameters, tip=None):
                parms = PwParticles3ParameterList("parameterList%i" % len(self.parameterlists), header=header, command=self.curCommand, tip=tip)
                self.add(parms, 388, self.parmsy)
                for name, value in parameters:
                        parms.addParameter(name, value)
                        self.curCommand = self.curCommand + 1
                self.parmsy = self.parmsy + parms.Height() + 6
                self.curCommand = self.curCommand + 1
                self.parameterlists.append(parms)
        def Values(self):
                values = {}
                for parmlist in self.parameterlists:
                        for key, value in parmlist.Values().items():
                                values[key] = value
                return values

def askTipAcceleration(event=None):
        dlg = PwParticles3Dialog()
        dlg.AddIllustration(IMG_TIP_ACCELERATION, width=565, height=379, x=27, y=71)
        dlg.Show()

def askTipVariance(event=None):
        dlg = PwParticles3Dialog()
        dlg.AddIllustration(IMG_TIP_VARIANCE, width=575, height=362, x=27, y=71)
        dlg.Show()

def askTipStartEnd(event=None):
        dlg = PwParticles3Dialog(infoHeader=STRING_STARTEND, infoBody=STRING_STARTEND_TIP)
        dlg.Show()

def askTipGravity(event=None):
        dlg = PwParticles3Dialog()
        dlg.AddIllustration(IMG_TIP_GRAVITY, width=589, height=348, x=27, y=71)
        dlg.Show()

class DlgShape(object):
        def __init__(self):
                self.shape_strings = {GEOM_BALL: STRING_BALL,
                          GEOM_TORUS: STRING_TORUS,
                          GEOM_PILL: STRING_PILL,
                          GEOM_SPRITE: STRING_SPRITE,
                          GEOM_CONE: STRING_CONE}
                self.shape_keys = {STRING_BALL: GEOM_BALL,
                              STRING_TORUS: GEOM_TORUS,
                              STRING_PILL: GEOM_PILL,
                              STRING_SPRITE: GEOM_SPRITE,
                              STRING_CONE: GEOM_CONE}
                self.lastshape = PRT3_PREFS.Get("shape")
                if self.shape_strings.has_key(self.lastshape):
                        defaultShapeStr = self.shape_strings[self.lastshape]
                        self.skipCustom = 0
                else:
                        defaultShapeStr = STRING_CUSTOM
                        self.skipCustom = 1
                self.dlg = PwParticles3Dialog(infoHeader=STRING_PARTICLE_SHAPE, infoBody=STRING_PARTICLE_SHAPE_INFO,
                                         tipHeader=STRING_BALL, tipBody=STRING_BALL_TIP, confirmbtn=IMG_BTN_OK)
                self.pane = PzrRadioPane("shapeRadios", initCommand=10150, itemsPerCol=3, initItem=defaultShapeStr)
                for shape, pic, hi in ((STRING_BALL, IMG_BALL, IMG_BALL_O),
                                       (STRING_PILL, IMG_PILL, IMG_PILL_O),
                                       (STRING_CONE, IMG_CONE, IMG_CONE_O),
                                       (STRING_TORUS, IMG_TORUS, IMG_TORUS_O),
                                       (STRING_SPRITE, IMG_SPRITE, IMG_SPRITE_O),
                                       (STRING_CUSTOM, IMG_CUSTOM, IMG_CUSTOM_O)):
                    self.pane.AddImageRadio(shape, pictRes=pic, hiliteRes=hi)
                self.pane.setOnClick(self.radioFunc)
                self.dlg.add(self.pane, 390, 75)
        def radioFunc(self, v=None):
                title, tip = { STRING_BALL : (STRING_BALL, STRING_BALL_TIP),
                              STRING_PILL : (STRING_PILL, STRING_PILL_TIP),
                              STRING_CONE : (STRING_CONE, STRING_CONE_TIP),
                              STRING_TORUS : (STRING_TORUS, STRING_TORUS_TIP),
                              STRING_SPRITE : (STRING_SPRITE, STRING_SPRITE_TIP),
                              STRING_CUSTOM : (STRING_CUSTOM, STRING_CUSTOM_TIP) }[v]
                prefkey = v
                if self.shape_keys.has_key(v):
                        PRT3_PREFS.Set("shape", self.shape_keys[v])
                        self.dlg.SetTip(title, tip)
                else:
                        if self.skipCustom:
                                obj = PRT3_PREFS.Get("shape")
                                self.skipCustom = 0
                        else:
                                obj = AskOpen(extensions=(".obj", ".obz"), dir=PRT3_PREFS.Get("dirShape"), title="Select OBJ", parent=self.dlg)
                        if obj:
                                PRT3_PREFS.Set("dirShape", obj)
                                PRT3_PREFS.Set("shape", obj)
                                self.dlg.SetTip(STRING_CUSTOM, os.path.basename(obj))
        def Show(self):
                if self.dlg.Show():
                        obj = PRT3_PREFS.Get("shape") #self.pane.get()
                        if obj[-1] == "z":
                                obj = obj[:-1] + "j"
                        return obj
                else:
                    return None

def askShape():
        geom = DlgShape().Show()
        if geom:
                return {"shape":geom}
        else:
                return None

class DlgNameCount(PwParticles3Dialog):
        def __init__(self):
                PwParticles3Dialog.__init__(self, confirmbtn=IMG_BTN_NEXT, infoHeader="Create Particle Figure", infoBody=" ")
                self.preset = None
                self.namer = PwParticles3Parameter(STRING_PARTICLE_NAME, font=FONT_PARM_DARK,  textwidth=154, command=10201, default=PRT3_PREFS.Get("name"))
                self.add(self.namer, 29, 112)
                self.add( PzrTextArea("namerInfo", text=FONT_BODY, message=STRING_PARTICLE_NAME_TIP), 29, 137)
                self.counter = PwParticles3Parameter(STRING_PARTICLE_COUNT, font=FONT_PARM_DARK, textwidth=154, command=10202, default=int(PRT3_PREFS.Get("count")))
                self.add(self.counter, 29, 172)
                self.add( PzrTextArea("countInfo", text=FONT_BODY, message=STRING_PARTICLE_COUNT_TIP), 29, 196)
                self.add( PzrImageButton("loader", callback=self.askLoadPreset, width=423, height=86, pictRes=14801, hiliteRes=14802, command=10109), 0, 340 )
        def Get(self):
                PRT3_PREFS.Set("name", self.namer.Value())
                PRT3_PREFS.Set("count", self.counter.Value())
                return {"name": self.namer.Value(),
                        "count": self.counter.Value(),
                        "preset": self.preset}
        def askLoadPreset(self, event=None):
                folder = PRT3_PREFS.Get("dirPreset")
                preset = AskOpen(extensions=(".pz2",".PZ2"), dir=folder, title="Load Particles 3 PZ2...", parent=self.dlg)
                self.preset = preset
                if preset:
                        import prt3Preset
                        data = prt3Preset.readPreset(self.preset)
                        for k, v in data.items():
                                PRT3_PREFS.Set(k, v)
                        PRT3_PREFS.Set("dirPreset", preset)
                        self.namer.SetValue(PRT3_PREFS.Get("name"))
                        self.counter.SetValue(int(PRT3_PREFS.Get("count")))
                        return preset
                else:
                        return None
                

def askNameCount():
        namer = DlgNameCount()
        if namer.Show():
                return namer.Get()
        else:
                return None

def askParameterDialog(btn=IMG_BTN_NEXT, header="Orbit", body="Tip", illus=None, illusWidth=310, illusHeight=218,
                       transformParms=None, simulationParms=None,
                       movementParms=None, accelerationParms=None, varianceParms=None):
        dlg = PwParticles3Dialog(confirmbtn=btn, tipHeader=header, tipBody=body)
        if illus:
                dlg.AddIllustration(illus, width=illusWidth, height=illusHeight)
        if simulationParms:
                dlg.AddParameterList("Emission",
                                     [(simulationParms[0][0], simulationParms[0][1]),
                                      (simulationParms[1][0], simulationParms[1][1]),
                                      (simulationParms[2][0], simulationParms[2][1])])
                dlg.AddParameterList("Animation",
                                     [(simulationParms[3][0], simulationParms[3][1]),
                                      (simulationParms[4][0], simulationParms[4][1])],
                                     tip=askTipStartEnd)
                dlg.AddParameterList("Gravity",
                                     [(simulationParms[5][0], simulationParms[5][1])],
                                     tip=askTipGravity)
        if transformParms:
                dlg.AddParameterList("Scale",
                                     [(transformParms[0][0], transformParms[0][1])])
                dlg.AddParameterList("Rotation",
                                     [(transformParms[1][0], transformParms[1][1]),
                                      (transformParms[2][0], transformParms[2][1]),
                                      (transformParms[3][0], transformParms[3][1])])
                dlg.AddParameterList("Offset",
                                     [(transformParms[4][0], transformParms[4][1]),
                                      (transformParms[5][0], transformParms[5][1]),
                                      (transformParms[6][0], transformParms[6][1])])
        if movementParms:
                dlg.AddParameterList("Movement",
                                     [(movementParms[0][0], movementParms[0][1]),
                                      (movementParms[1][0], movementParms[1][1]),
                                      (movementParms[2][0], movementParms[2][1])])
        if accelerationParms:
                dlg.AddParameterList("Acceleration",
                                     [(accelerationParms[0][0], accelerationParms[0][1]),
                                      (accelerationParms[1][0], accelerationParms[1][1]),
                                      (accelerationParms[2][0], accelerationParms[2][1])],
                                     tip=askTipAcceleration)
        if varianceParms:
                dlg.AddParameterList("Variance",
                                     [(varianceParms[0][0], varianceParms[0][1])],
                                     tip=askTipVariance)
        if dlg.Show():
                return dlg.Values()
        else:
                return None

def askTransform():
        global CURRENT_ACTOR
        if not CURRENT_ACTOR:
                return None
        pscale = CURRENT_ACTOR.Parameter(PARM_PSCALE).Value()
        pxrot = CURRENT_ACTOR.Parameter(PARM_PXROTATE).Value()
        pyrot = CURRENT_ACTOR.Parameter(PARM_PYROTATE).Value()
        pzrot = CURRENT_ACTOR.Parameter(PARM_PZROTATE).Value()
        pxtran = CURRENT_ACTOR.Parameter(PARM_PXTRAN).Value()
        pytran = CURRENT_ACTOR.Parameter(PARM_PYTRAN).Value()
        pztran = CURRENT_ACTOR.Parameter(PARM_PZTRAN).Value()
        dlg = PwParticles3Dialog(confirmbtn=IMG_BTN_NEXT, infoHeader=STRING_TRANSFORM, infoBody=STRING_TRANSFORM_TIP)
        #dlg.AddIllustration(IMG_TRANSFORM, width=310, height=218)
        dlg.AddParameterList("Scale",
                [(PARM_PSCALE, pscale)])
        dlg.AddParameterList("Rotation",
                [(PARM_PXROTATE, pxrot),
                (PARM_PYROTATE, pyrot),
                (PARM_PZROTATE, pzrot)])
        dlg.AddParameterList("Offset",
                [(PARM_PXTRAN, pxtran),
                (PARM_PYTRAN, pytran),
                (PARM_PZTRAN, pztran)])
        if dlg.Show():
                return dlg.Values()
        else:
                return None

def askSimulation():
        global CURRENT_ACTOR
        if not CURRENT_ACTOR:
                return None
        emis = int(CURRENT_ACTOR.Parameter(PARM_EMISSION).Value())
        if CURRENT_ACTOR.Parameter(PARM_RECYCLE).Value():
                recy = "True"
        else:
                recy = "False"
        span = int(CURRENT_ACTOR.Parameter(PARM_LIFESPAN).Value())
        start = int(CURRENT_ACTOR.Parameter(PARM_START).Value())
        end = int(CURRENT_ACTOR.Parameter(PARM_END).Value())
        grav = CURRENT_ACTOR.Parameter(PARM_GRAVITY).Value()
        return askParameterDialog(btn=IMG_BTN_NEXT, header=STRING_SIMULATION, body=STRING_SIMULATION_TIP,
                                  illus=IMG_SIMULATION, illusWidth=299, illusHeight=246,
                                  simulationParms = [(PARM_EMISSION, emis), (PARM_RECYCLE, recy), (PARM_LIFESPAN, span),
                                                     (PARM_START, start), (PARM_END, end),
                                                     (PARM_GRAVITY, grav)] )
def askVelocity():
        global CURRENT_ACTOR
        if not CURRENT_ACTOR:
                return None
        x = CURRENT_ACTOR.Parameter(PARM_VELOCITYX).Value()
        y = CURRENT_ACTOR.Parameter(PARM_VELOCITYY).Value()
        z = CURRENT_ACTOR.Parameter(PARM_VELOCITYZ).Value()
        ax = CURRENT_ACTOR.Parameter(PARM_ACCELERATIONX).Value()
        ay = CURRENT_ACTOR.Parameter(PARM_ACCELERATIONY).Value()
        az = CURRENT_ACTOR.Parameter(PARM_ACCELERATIONZ).Value()
        v = CURRENT_ACTOR.Parameter(PARM_VELOCITYVAR).Value()
        return askParameterDialog(btn=IMG_BTN_NEXT, header=STRING_VELOCITY, body=STRING_VELOCITY_TIP,
                                  illus=IMG_VELOCITY, illusWidth=308, illusHeight=234,
                                  movementParms = [(PARM_VELOCITYX, x), (PARM_VELOCITYY, y), (PARM_VELOCITYZ, z)],
                                  accelerationParms = [(PARM_ACCELERATIONX, ax), (PARM_ACCELERATIONY, ay), (PARM_ACCELERATIONZ, az)],
                                  varianceParms = [(PARM_VELOCITYVAR, v)] )

def askOrbit():
        global CURRENT_ACTOR
        if not CURRENT_ACTOR:
                return None
        x = CURRENT_ACTOR.Parameter(PARM_ORBITX).Value()
        y = CURRENT_ACTOR.Parameter(PARM_ORBITY).Value()
        z = CURRENT_ACTOR.Parameter(PARM_ORBITZ).Value()
        ax = CURRENT_ACTOR.Parameter(PARM_ORBITAX).Value()
        ay = CURRENT_ACTOR.Parameter(PARM_ORBITAY).Value()
        az = CURRENT_ACTOR.Parameter(PARM_ORBITAZ).Value()
        v = CURRENT_ACTOR.Parameter(PARM_ORBITVAR).Value()
        return askParameterDialog(btn=IMG_BTN_NEXT, header=STRING_ORBIT, body=STRING_ORBIT_TIP,
                                  illus=IMG_ORBIT,
                                  movementParms = [(PARM_ORBITX, x), (PARM_ORBITY, y), (PARM_ORBITZ, z)],
                                  accelerationParms = [(PARM_ORBITAX, ax), (PARM_ORBITAY, ay), (PARM_ORBITAZ, az)],
                                  varianceParms = [(PARM_ORBITVAR, v)] )

def askSpin():
        global CURRENT_ACTOR
        if not CURRENT_ACTOR:
                return None
        x = CURRENT_ACTOR.Parameter(PARM_SPINX).Value()
        y = CURRENT_ACTOR.Parameter(PARM_SPINY).Value()
        z = CURRENT_ACTOR.Parameter(PARM_SPINZ).Value()
        ax = CURRENT_ACTOR.Parameter(PARM_SPINAX).Value()
        ay = CURRENT_ACTOR.Parameter(PARM_SPINAY).Value()
        az = CURRENT_ACTOR.Parameter(PARM_SPINAZ).Value()
        v = CURRENT_ACTOR.Parameter(PARM_SPINVAR).Value()
        return askParameterDialog(btn=IMG_BTN_NEXT, header=STRING_SPIN, body=STRING_SPIN_TIP,
                                  illus=IMG_SPIN, illusWidth=253, illusHeight=236,
                                  movementParms = [(PARM_SPINX, x), (PARM_SPINY, y), (PARM_SPINZ, z)],
                                  accelerationParms = [(PARM_SPINAX, ax), (PARM_SPINAY, ay), (PARM_SPINAZ, az)],
                                  varianceParms = [(PARM_SPINVAR, v)] )

def askGrow():
        global CURRENT_ACTOR
        if not CURRENT_ACTOR:
                return None
        x = CURRENT_ACTOR.Parameter(PARM_GROWX).Value()
        y = CURRENT_ACTOR.Parameter(PARM_GROWY).Value()
        z = CURRENT_ACTOR.Parameter(PARM_GROWZ).Value()
        ax = CURRENT_ACTOR.Parameter(PARM_GROWAX).Value()
        ay = CURRENT_ACTOR.Parameter(PARM_GROWAY).Value()
        az = CURRENT_ACTOR.Parameter(PARM_GROWAZ).Value()
        v = CURRENT_ACTOR.Parameter(PARM_GROWVAR).Value()
        return askParameterDialog(btn=IMG_BTN_OK, header=STRING_GROW, body=STRING_GROW_TIP,
                                  illus=IMG_GROW, illusWidth=336, illusHeight=209,
                                  movementParms = [(PARM_GROWX, 0.0), (PARM_GROWY, 0.0), (PARM_GROWZ, 0.0)],
                                  accelerationParms = [(PARM_GROWAX, 0.0), (PARM_GROWAY, 0.0), (PARM_GROWAZ, 0.0)],
                                  varianceParms = [(PARM_GROWVAR, 0.0)] )

class PwWizard(object):
        def __init__(self, *args):
                self.pages = []
                for arg in args:
                        self.pages.append(arg)
                self.current = 0
                self.values = {}
        def ShowPage(self, x):
                result = self.pages[x]()
                if result:
                        self.storeValues(result)
                        return 1
                else:
                        return None
        def Previous(self):
                self.current = self.current - 1
                return self.ShowPage(self.current)
        def Next(self):
                self.current = self.current + 1
                return self.ShowPage(self.current)
        def storeValues(self, result):
                for key, value in result.items():
                        self.values[key] = value
        def Show(self):
                result = 1
                while result and self.current < len(self.pages):
                        result = self.ShowPage(self.current)
                        self.current = self.current + 1
                if result:
                        return self.values
                else:
                        return {}

def askConfigureGroup():
        values = PwWizard(askSimulation, askTransform, askVelocity, askOrbit, askSpin, askGrow).Show()
        if not values:
                return None
        body = poser.Scene().CurrentFigure().ParentActor()
        for name, value in values.items():
                parm = body.Parameter(name)
                if parm:
                        parm.SetValue(value)

def askConfigureAttractor():
        global CURRENT_ACTOR
        if not CURRENT_ACTOR:
                return None
        stre = CURRENT_ACTOR.Parameter(PARM_ATTRACTION).Value()
        rang = CURRENT_ACTOR.Parameter(PARM_RANGE).Value()
        fall = CURRENT_ACTOR.Parameter(PARM_FALLOFF).Value()
        dlg = PwParticles3Dialog(confirmbtn=IMG_BTN_OK, infoHeader=STRING_ATTRACTOR, infoBody=STRING_ATTRACTOR_TIP)
        dlg.AddIllustration(IMG_ATTRACTOR, width=327, height=154, y=270)
        dlg.AddParameterList("Simulation",
                             [(PARM_ATTRACTION, stre),
                              (PARM_RANGE, rang),
                              (PARM_FALLOFF, fall)])
        if dlg.Show():
                values = dlg.Values()
                for name, value in values.items():
                        parm = CURRENT_ACTOR.Parameter(name)
                        if parm:
                                parm.SetValue(value)
                return values
        else:
                return None

def askConfigureDeflector():
        return ErrorBox("Deflector")

def askConfigureEmitter():
        global CURRENT_ACTOR
        if not CURRENT_ACTOR:
                return None
        v = CURRENT_ACTOR.Parameter(PARM_EMISSIONANGLE).Value()
        dlg = PwParticles3Dialog(confirmbtn=IMG_BTN_OK, tipHeader=STRING_EMITTER, tipBody=STRING_EMITTER_TIP)
        dlg.AddIllustration(IMG_EMITTER, width=305, height=253)
        dlg.AddParameterList("Simulation",
                             [(PARM_EMISSIONANGLE, v)])
        if dlg.Show():
                values = dlg.Values()
                for name, value in values.items():
                        parm = CURRENT_ACTOR.Parameter(name)
                        if parm:
                                parm.SetValue(value)
                return values
        else:
                return None

def askConfigure(actor):
        global CURRENT_ACTOR
        CURRENT_ACTOR = actor
        try:
                PRT3_PREFS.Set("lastActor", CURRENT_ACTOR.InternalName())
        except:
                try:
                        CURRENT_ACTOR = poser.Scene().ActorByInternalName(PRT3_PREFS.Get("lastActor"))
                except:
                        CURRENT_ACTOR = None
        if CURRENT_ACTOR:
                if CURRENT_ACTOR.IsCamera() or CURRENT_ACTOR.IsLight() or CURRENT_ACTOR.IsBodyPart():
                        CURRENT_ACTOR = poser.Scene().CurrentFigure()
                        if CURRENT_ACTOR:
                                CURRENT_ACTOR = CURRENT_ACTOR.ParentActor()
                        else:
                                return ErrorBox("No Particles 3 element selected.")
                PRT3_PREFS.Set("lastActor", CURRENT_ACTOR.InternalName())
                parm = CURRENT_ACTOR.Parameter(PARM_TYPE)
                if parm:
                        v = parm.Value()
                        if v == SYSTEM_TYPE or v == GROUP_TYPE or v == PARTICLE_TYPE:
                                return askConfigureGroup()
                        elif v == ATTRACTOR_TYPE:
                                return askConfigureAttractor()
                        elif v == DEFLECTOR_TYPE:
                                return askConfigureDeflector()
                        elif v == EMITTER_TYPE:
                                return askConfigureEmitter()
        ErrorBox("No Particles 3 element selected.")

def askCreateFigure():
        values = PwWizard(askNameCount, askShape).Show()
        if values:
                shape = values["shape"]
                shape_nums = {GEOM_BALL: SHAPE_BALL,
                          GEOM_TORUS: SHAPE_TORUS,
                          GEOM_PILL: SHAPE_PILL,
                          GEOM_SPRITE: SHAPE_SPRITE,
                          GEOM_CONE: SHAPE_CONE}
                if shape_nums.has_key(shape):
                        shape = shape_nums[shape]
                import prt3Core
                prt3Core.createSystem(values["name"], [("Particle Group", values["count"], shape)])
                if values["preset"]:
                        import prt3Preset
                        prt3Preset.applyPreset(values["preset"])
        else:
                pass

def runSimulation(options):
        options = askSimulate()
        if options:
            scene = poser.Scene()
            targets = options["targets"]
            inplace = options["inPlace"]
            for target in targets:
                figure = scene.Figure(target)
                simulate(buildSystemFrom(figure), inplace=inplace)

def askSimulate():
        def runSim(event=None):
                from prt3Sim import simulate
                from prt3Core import buildSystemFrom
                import string
                doWhat = selectOpts.index(sim_what.get())
                PRT3_SCENEPREFS.Set("simulateFigures", string.join(sim_figs.get(), ";"))
                PRT3_SCENEPREFS.Set("simulateInPlace", sim_in_place.Value())
                PRT3_SCENEPREFS.Set("simulateWhat", doWhat)
                targets = []
                if doWhat == 0:
                        targets = [poser.Scene().CurrentFigure().Name()]
                elif doWhat == 1:
                        targets = figNames
                else:
                        targets = sim_figs.get()
                options = {"inPlace": sim_in_place.Value(),
                        "targets": targets}
                scene = poser.Scene()
                targets = options["targets"]
                inplace = options["inPlace"]
                for target in targets:
                        figure = scene.Figure(target)
                        simulate(buildSystemFrom(figure), inplace=inplace, update=redraw)
                redraw("Simulation complete.")
        # Test to see if there's a particle figure selected
        proceed = 0
        fig = poser.Scene().CurrentFigure()
        if fig:
                parm = fig.ParentActor().Parameter(PARM_TYPE)
                if parm:
                        if parm.Value() == GROUP_TYPE or parm.Value() == SYSTEM_TYPE:
                                proceed = 1
        if not proceed:
                ErrorBox("No particle figure selected.")
                return None
        dlg = PwParticles3Dialog(confirmbtn=IMG_BTN_SIM, infoHeader=STRING_RUN_SIMS, infoBody=" ",
                                 confirmcmd=10450, confirmcb=runSim)
        x, y = 29, 112
        # Simulate in place
        sim_in_place = PwParticles3Parameter(STRING_SIMULATE_IN_PLACE, textwidth=154, command=10001, default=0, suffix=" frames")
        dlg.add(sim_in_place, x, y)
        y = y + 25
        # Simulate in place tip text
        dlg.add( PzrTextArea("inplaceInfo", text=FONT_BODY, message=STRING_SIMULATE_IN_PLACE_INFO), x, y)
        # Simulate what text
        y = y + 72
        dlg.add( PzrTextArea("simwhatInfo", text=FONT_PARAMETER, message=STRING_RUN_SIMS_FOR), x, y)
        # Select what to simulate (radios)
        sim_what = PzrRadioPane(initCommand=10002, text=FONT_RADIO)
        selectOpts = [STRING_SELECTED_FIG, STRING_ALL_FIG, STRING_THESE_FIG]
        for opt in selectOpts:
                sim_what.AddRadiobutton(opt)
        y = y + 25
        dlg.add(sim_what, x + 25, y)
        # Select specific particle figures
        import prt3Core
        figs = {}
        valueMap = []
        select = PRT3_SCENEPREFS.Get("simulateFigures")
        if not isinstance(select, list):
                select = [select]
        for system in prt3Core.getSystems():
                figs[system.Name()] = system
                if system.Name() in select:
                        valueMap.append(1)
                else:
                        valueMap.append(0)
        figNames = figs.keys()
        figNames.sort()
        sim_figs = PzrCheckPane(groupID=34, initCommand=10101, text=FONT_RADIO, itemsPerCol=6, valueMap=valueMap)
        for figName in figNames:
                sim_figs.AddCheckbutton(figName, width=164)
        y = y + 64
        dlg.add(sim_figs, x + 50, y)
        # Set values according to prefs
        sim_in_place.SetValue(PRT3_SCENEPREFS.Get("simulateInPlace"))
        sim_what.set(selectOpts[PRT3_SCENEPREFS.Get("simulateWhat")])
        #sim_run = PzrButton("Run Simulation", callback=runSim, command=10901)
        #dlg.add(sim_run, 22, 420)
        sim_run_message = PzrMessage("RunMessage", text=FONT_PARAMETER)
        dlg.add(sim_run_message, 22, 432)
        sim_run_message.configure(title="")
        def redraw(message, dialog=dlg, target=sim_run_message):
                target.SetText(dialog, message)
        # Show the dialog
        dlg.Show()
        """
        if dlg.Show():
                import string
                PRT3_SCENEPREFS.Set("simulateFigures", string.join(sim_figs.get(), ";"))
                PRT3_SCENEPREFS.Set("simulateInPlace", sim_in_place.Value())
                doWhat = selectOpts.index(sim_what.get())
                PRT3_SCENEPREFS.Set("simulateWhat", doWhat)
                targets = []
                if doWhat == 0:
                        targets = [poser.Scene().CurrentFigure().Name()]
                elif doWhat == 1:
                        targets = figNames
                else:
                        targets = sim_figs.get()
                return {"inPlace": sim_in_place.Value(),
                        "targets": targets}
        else:
                return None
        """

def askSavePreset():
        out = AskSaveAs(extensions=(".pz2",".PZ2"), dir=PRT3_PREFS.Get("dirPreset"))
        if out:
                PRT3_PREFS.Set("dirPreset", out)
                fig = poser.Scene().CurrentFigure()
                if fig:
                        import prt3Core
                        if prt3Core.isParticleFigure(fig):
                                import prt3Preset
                                prt3Preset.savePreset(fig, out)
                                return 1
                else:
                        return ErrorBox("No Particles 3 figure selected.")

if __name__ == '__main__':
        #askSimulate()
        #askCreateFigure()
        askConfigure(poser.Scene().CurrentActor())
        """
        askSimulation()
        askTransform()
        askVelocity()
        askOrbit()
        askSpin()
        askGrow()
        """
        #print askShape(STRING_BALL)
